home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / c / cppcom.com / COMPORTS.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-14  |  10.0 KB  |  209 lines

  1. /***************************************************************************
  2. These C++ classes are copyright 1990, by William Herrera.
  3. All those who put this code or its derivatives in a commercial product MUST
  4. mention this copyright in their documentation for users of the products in
  5. which this code or its derivative classes are used.  Otherwise, this code
  6. may be freely distributed and freely used for any purpose.
  7.  
  8. Enhancements: 1991 by David Orme
  9.     *  General cleanup.
  10.             - I/O now takes advantage of C++ overloading.
  11.             - Serial port I/O functionality now only in Serial class.
  12.             - Modem functionality now only in Modem class.
  13.     *  Possible to easily implement file Xfr prots now.
  14.     *  CCITT CRC-16 class added                            -- 2-20-1991
  15.     *  BIOS Timer class added                                -- 2-22-1991
  16.     *  Optional timeout on all input routines added    -- 2-25-1991
  17.  
  18. ***************************************************************************/
  19.  
  20. // file comports.cpp defines various uart classes.
  21.  
  22. #include <stdlib.h>
  23.  
  24. #include "comports.hpp"
  25.  
  26. static const int insize = 1024;
  27. static const int outsize = 4096;
  28.  
  29. // C++ 2.0 requires that static members be declared globally...
  30.  
  31. COM1 * COM1::this_ptr;
  32. COM2 * COM2::this_ptr;
  33. COM3 * COM3::this_ptr;
  34. COM4 * COM4::this_ptr;
  35.  
  36.  
  37. #ifdef __TURBOC__
  38.  
  39. #define DEFINE_COMX(COM, x, driver)                     \
  40. CharQueue * COM##x::inq = new CharQueue(insize);        \
  41. CharQueue * COM##x::outq = new CharQueue(outsize);      \
  42. DRIVER COM##x::driver = driver##x;                      \
  43. COM##x::COM##x()                                        \
  44. {                                                       \
  45.     this_ptr = this;                                    \
  46.     DoIfNoCarrier = DoNothing;                          \
  47.     DoOnRing = DoNothing;                                \
  48.     if(RegisterDriver(##x, driver##x) != 0)             \
  49.         exit(1);                                        \
  50. }                                                       \
  51. COM##x::~COM##x()                                       \
  52. {                                                       \
  53.     if(RestoreDriver(##x) != 0)                         \
  54.         exit(1);                                        \
  55. }                                                       \
  56. void COM##x::SetDoIfNoCarrier(void (*f)())              \
  57. {                                                       \
  58.     DoIfNoCarrier = f;                                  \
  59. }                                                       \
  60. void COM##x::SetDoOnRing(void (*f)())                    \
  61. {                                                       \
  62.     DoOnRing = f;                                        \
  63. }                                                       \
  64. void COM##x::FlushOutput()                              \
  65.     { while (!outq->IsEmpty()) {;} }                    \
  66. void COM##x::SendChar(char ch)                          \
  67. {                                                       \
  68.     while(outq->IsFull())                               \
  69.         ;    /* wait til queue transmitted by driver */ \
  70.     outq->Add(ch);                                      \
  71.     SetIER_Transmit(true);                              \
  72. }                                                       \
  73. int COM##x::GetChar()                                   \
  74. {                                                       \
  75.     return inq->Get();                                  \
  76.     /* remember, empty charqueue flag is -1. */         \
  77. }                                                       \
  78.                                                         \
  79. void interrupt driver##x(...)                           \
  80. {                                                       \
  81.     /* driver for comm interrupt. */                    \
  82.     COM##x * cptr = COM##x::this_ptr;                   \
  83.     com_interrupt_t i;                                  \
  84.     while((i = cptr->GetIntrType()) != NONE_PENDING)    \
  85.     {                                                   \
  86.         disable();  /* don't let another come in */     \
  87.         switch((int)i & 0xFF)                           \
  88.         {                                               \
  89.             case (int)TRANSMIT_READY :                  \
  90.                 if(COM##x::outq->IsEmpty())             \
  91.                     cptr->SetIER_Transmit(false);       \
  92.                 else                                    \
  93.                     cptr->                              \
  94.                     TransmitChar(COM##x::outq->Get());  \
  95.              break;                                   \
  96.             case (int)RECEIVE_READY:                    \
  97.                 if(!COM##x::inq->IsFull())              \
  98.                     COM##x::inq->                       \
  99.                         Add(cptr->ReceiveChar());       \
  100.                 break;                                  \
  101.             case (int)NO_CARRIER:                       \
  102.                 (*cptr->DoIfNoCarrier)();               \
  103.              break;                                  \
  104.             case (int)RING:                                \
  105.                 (*cptr->DoOnRing)();                    \
  106.              break;                                     \
  107.             default:                                    \
  108.             /* all others here. the function */         \
  109.             /* GetIntrType() should have already */     \
  110.             /* cleaned up the other interrupt flags. */ \
  111.                 break;                                  \
  112.         }                                               \
  113.         enable();  /* other interrupts now ok */        \
  114.     }                                                   \
  115.     outportb( 0x20, 0x20);                              \
  116. }                                                       
  117.                                                         
  118.  
  119.  
  120.  
  121. #else ifdef __ZTC__
  122.  
  123. #define DEFINE_COMX(COM, x, driver)                     \
  124. CharQueue * COM##x::inq = new CharQueue(insize);        \
  125. CharQueue * COM##x::outq = new CharQueue(outsize);      \
  126. DRIVER COM##x::driver = driver##x;                      \
  127. COM##x::COM##x()                                        \
  128. {                                                       \
  129.     this_ptr = this;                                    \
  130.     DoIfNoCarrier = DoNothing;                          \
  131.     DoOnRing = DoNothing;                                \
  132.     if(RegisterDriver(##x, driver##x) != 0)             \
  133.         exit(1);                                        \
  134. }                                                       \
  135. COM##x::~COM##x()                                       \
  136. {                                                       \
  137.     if(RestoreDriver(##x) != 0)                         \
  138.         exit(1);                                        \
  139. }                                                       \
  140. void COM##x::SetDoIfNoCarrier(void (*f)())              \
  141. {                                                       \
  142.     DoIfNoCarrier = f;                                  \
  143. }                                                       \
  144. void COM##x::SetDoOnRing(void (*f)())                    \
  145. {                                                       \
  146.     DoOnRing = f;                                        \
  147. }                                                       \
  148. void COM##x::FlushOutput()                              \
  149.     { while (!outq->IsEmpty()) {;} }                    \
  150. void COM##x::SendChar(char ch)                          \
  151. {                                                       \
  152.     while(outq->IsFull())                               \
  153.         ;                                               \
  154.     outq->Add(ch);                                      \
  155.     SetIER_Transmit(true);                              \
  156. }                                                       \
  157. int COM##x::GetChar()                                   \
  158. {                                                       \
  159.     return inq->Get();                                  \
  160. }                                                       \
  161.                                                         \
  162. int driver##x(INT_DATA *pd)                             \
  163. {                                                       \
  164.     COM##x * cptr = COM##x::this_ptr;                   \
  165.     com_interrupt_t i;                                  \
  166.     while((i = cptr->GetIntrType()) != NONE_PENDING)    \
  167.     {                                                   \
  168.         disable();  /* don't let another come in */     \
  169.         switch((int)i & 0xFF)                           \
  170.         {                                               \
  171.             case (int)TRANSMIT_READY :                  \
  172.                 if(COM##x::outq->IsEmpty())             \
  173.                     cptr->SetIER_Transmit(false);       \
  174.                 else                                    \
  175.                     cptr->                              \
  176.                     TransmitChar(COM##x::outq->Get());  \
  177.               break;                                  \
  178.             case (int)RECEIVE_READY:                    \
  179.                 if(!COM##x::inq->IsFull())              \
  180.                     COM##x::inq->                       \
  181.                         Add(cptr->ReceiveChar());       \
  182.                 break;                                  \
  183.             case (int)NO_CARRIER:                       \
  184.                 (*cptr->DoIfNoCarrier)();               \
  185.              break;                                  \
  186.             case (int)RING:                                \
  187.                 (*cptr->DoOnRing)();                    \
  188.              break;                                     \
  189.             default:                                    \
  190.                 break;                                  \
  191.         }                                               \
  192.         enable();  /* other interrupts now ok */        \
  193.     }                                                   \
  194.     outportb( 0x20, 0x20);                              \
  195.     return 1;                                           \
  196. }                                                       
  197.  
  198.  
  199. #endif
  200.  
  201. // To define up to four com ports, you should
  202. // declare one or more of the following statements:
  203.  
  204. DEFINE_COMX(COM, 1, driver)
  205. DEFINE_COMX(COM, 2, driver)
  206. DEFINE_COMX(COM, 3, driver)
  207. DEFINE_COMX(COM, 4, driver)
  208.  
  209.